﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Linq;

namespace AutoUI
{
    /// <summary>
    ///
    /// </summary>
    [DefaultProperty("GradientColor_")]
    public class AutoShape
    {
        private PointF drawPoint = new PointF(0.0f, 0.0f);
        private int count = 3;

        #region Properties

        /// <summary>
        /// 形状需要旋转的角度
        /// </summary>
        [DisplayName("4.旋转角度"), Category("2.位置和大小")]
        public float Angle { get; set; }

        [Browsable(false)]
        public Brush Brush { get; set; } = new SolidBrush(Color.Red);

        /// <summary>
        /// 填充画刷的类型
        /// </summary>
        [DisplayName("3.画刷的类型"), Category("1.类型")]
        public EnumBrushType BrushType { get; set; } = EnumBrushType.SolidBrush;

        /// <summary>
        /// 渐变过渡设置
        /// </summary>
        [Browsable(false)]
        public ColorBlend ColorBlend { get; set; }

        /// <summary>
        /// EnumShapeType为多边形或者星形的时候，需要生成的数量
        /// </summary>
        [DisplayName("个数"), Category("多边形.星形.环形刻度")]
        public int Count
        {
            get => count; set
            {
                if (value > 2)
                {
                    count = value;
                }
            }
        }

        /// <summary>
        /// 星形内圆大小(默认0.4),占外圆的比例;设置太大,可能会没有星形效果;
        /// </summary>
        [DisplayName("内圆大小"), Category("多边形.星形.环形刻度"), Description("星形内圆大小(默认0.4),占外圆的比例;设置太大,可能会没有星形效果;")]
        public float InnerRadiusScale { get; set; } = 0.4f;

        [DisplayName("星角大小"), Category("多边形.星形.环形刻度"), Description("正N角星的时候,星角的大小")]
        public float StarAngel { get; set; }

        /// <summary
        /// 绘图原点:相对于零点的偏移,主要用于需要绕点旋转的时候
        /// </summary>
        [TypeConverter(typeof(PointFConvertor)), DisplayName("3.绘图原点"), Category("2.位置和大小"), Description("默认原点(0,0),范围(0-1)主要用于需要绕点旋转的时候")]
        public PointF DrawPoint
        {
            get => drawPoint; set
            {
                if (value.X >= 0 && value.X < 1)
                {
                    drawPoint = value;
                }
            }
        }

        /// <summary>
        /// 渐变结束色
        /// </summary>
        [DisplayName("2.结束颜色"), Category("3.颜色设置")]
        [Editor(typeof(ColorEditorExt), typeof(UITypeEditor))]
        public Color EndColor { get; set; } = Color.White;

        /// <summary>
        /// 渐变色的中心点
        /// </summary>
        [TypeConverter(typeof(PointFConvertor)), DisplayName("2.渐变中心位置"), Category("2.位置和大小"), Description("默认原点(0,0)")]
        public PointF GradientCenterPoint { get; set; } = new PointF(0.0f, 0.0f);

        /// <summary>
        /// 过渡颜色设置
        /// </summary>
        [DisplayName("3.过渡颜色设置"), Category("3.颜色设置")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [Localizable(true)]
        [MergableProperty(false)]
        public List<GradientColor> GradientColor_ { get; set; } = new List<GradientColor>();

        [Browsable(false)]
        public GraphicsPath Path { get; internal set; }

        /// <summary>
        /// 形状的位置，相对于控件而言
        /// </summary>
        [TypeConverter(typeof(PointFConvertor)), DisplayName("1.位置"), Category("2.位置和大小")]
        public PointF Position { get; set; } = new PointF(0.5f, 0.5f);

        /// <summary>
        /// 形状的大小比例，相对于控件而言
        /// </summary>
        [TypeConverter(typeof(PointFConvertor)), DisplayName("1.大小"), Category("2.位置和大小")]
        public PointF Scale { get; set; } = new PointF(0.5f, 0.2f);

        /// <summary>
        /// 形状的类型
        /// </summary>
        [DisplayName("1.形状"), Description("多边形,星形,圆角矩形等等...."), Category("1.类型")]
        public EnumShapeType ShapeType { get; set; }

        /// <summary>
        /// 渐变结束色,背景色
        /// </summary>
        [DisplayName("1.开始颜色"), Category("3.颜色设置")]
        [Editor(typeof(ColorEditorExt), typeof(UITypeEditor))]
        public Color StartColor { get; set; } = Color.Red;

        /// <summary>
        /// 风格类型
        /// </summary>
        [DisplayName("2.风格"), Category("1.类型")]
        public EnumStytle Style { get; set; }

        [DisplayName("4.是否填充"), Category("1.类型")]
        public EnumDrawOrFill DrawOrFill { get; set; }

        /// <summary>
        ///
        /// </summary>
        [Browsable(false)]
        public Pen Pen { get; internal set; } = new Pen(Color.Black);

        /// <summary>
        /// 边框颜色
        /// </summary>
        [DisplayName("4.画笔颜色"), Category("3.颜色设置")]
        [Editor(typeof(ColorEditorExt), typeof(UITypeEditor))]
        public Color BoderColor { get; set; } = Color.Black;

        [DisplayName("5.线条/刻度宽度"), Category("1.类型")]
        public float BoderWidth { get; set; }

        [DisplayName("1.起始角度"), Category("环形刻度条")]
        public float StartAngel { get; set; } = 0;

        [DisplayName("2.划过角度"), Category("环形刻度条")]
        public float SweepAngel { get; set; } = 180;

        #endregion Properties

        #region Methods

        /// <summary>
        ///
        /// </summary>
        /// <param name="width">控件宽</param>
        /// <param name="height">控件高</param>
        internal void CreatePath(int width, int height)
        {
            float w = width * Scale.X;
            float h = height * Scale.Y;
            var offsetx = width * Position.X;
            var offsety = height * Position.Y;
            var length = Math.Min(w, h);
            Matrix matrix = new Matrix();
            matrix.Rotate(-Angle);
            matrix.Translate(offsetx, offsety, MatrixOrder.Append);
            var offsetpoint = new PointF(DrawPoint.X * length, DrawPoint.Y * length);
            switch (ShapeType)
            {
                case EnumShapeType.正多边形:
                    Path = Shapes.CreateRegularPolygon(offsetpoint, length, Count);
                    break;

                case EnumShapeType.星形:
                    if (Style == EnumStytle.Stytle1)//正N角星
                    {
                        if (Count > 4)
                        {
                            var angel = (360.0f / Count) / 2;
                            var dingjiao = (90 - 2 * angel) * 2;
                            InnerRadiusScale = (float)(Math.Sin((dingjiao / 2) * SysConst.Angle) / Math.Cos(angel * SysConst.Angle));
                            StarAngel = dingjiao;
                        }
                    }
                    Path = Shapes.CreateStar(offsetpoint, length, InnerRadiusScale, Count, Style);
                    break;

                case EnumShapeType.指针:
                    Path = Shapes.CreateNeedle(offsetpoint, w, h, Style);

                    break;

                case EnumShapeType.环形刻度:
                    DrawOrFill = EnumDrawOrFill.OnlyDraw;
                    Path = Shapes.CreateWaitCircleSpoke(offsetpoint, length, InnerRadiusScale, Count, StartAngel, SweepAngel, Style);
                    break;

                case EnumShapeType.圆形:
                    Path = new GraphicsPath();
                    Path.AddEllipse(new CircleF(offsetpoint, length));
                    break;
            }
            InitBrush(Path, matrix, w, h);
            Path.Transform(matrix);
        }

        /// <summary>
        /// 初始化Brush
        /// </summary>
        /// <param name="path"></param>
        /// <param name="matrix"></param>
        /// <param name="w"></param>
        /// <param name="h"></param>
        private void InitBrush(GraphicsPath path, Matrix matrix, float w, float h)
        {
            switch (DrawOrFill)
            {
                case EnumDrawOrFill.OnlyDraw:
                    Pen.Color = BoderColor;
                    Pen.Width = BoderWidth;
                    break;

                case EnumDrawOrFill.OnlyFill:
                    switch (BrushType)
                    {
                        case EnumBrushType.SolidBrush:
                            Brush = new SolidBrush(StartColor);
                            break;

                        case EnumBrushType.PathGradientBrush:
                            List<Color> colors = new List<Color>();
                            colors.Add(StartColor);
                            colors.AddRange(GradientColor_.Select(x => x.Color));
                            colors.Add(EndColor);
                            List<float> points = new List<float>();
                            points.Add(0);
                            points.AddRange(GradientColor_.Select(x => x.ColorPositon));
                            points.Add(1);

                            ColorBlend = new ColorBlend()
                            {
                                Colors = colors.ToArray(),
                                Positions = points.ToArray()
                            };
                            //var pb = new PathGradientBrush(Path);

                            //pb.InterpolationColors = ColorBlend;
                            //pb.CenterPoint = new PointF(GradientCenterPoint.X * w + DrawPoint.X * w, GradientCenterPoint.Y * h + DrawPoint.Y * h);
                            //pb.Transform = matrix;
                            //Brush = pb;
                            Brush = new PathGradientBrush(Path);
                            ((PathGradientBrush)Brush).InterpolationColors = ColorBlend;
                            ((PathGradientBrush)Brush).CenterPoint = new PointF(GradientCenterPoint.X * w + DrawPoint.X * w, GradientCenterPoint.Y * h + DrawPoint.Y * h);
                            ((PathGradientBrush)Brush).Transform = matrix;
                            break;

                        default:
                            break;
                    }
                    break;

                case EnumDrawOrFill.DrawAndFill:
                    Pen.Color = BoderColor;
                    Pen.Width = BoderWidth;
                    switch (BrushType)
                    {
                        case EnumBrushType.SolidBrush:
                            Brush = new SolidBrush(StartColor);
                            break;

                        case EnumBrushType.PathGradientBrush:
                            List<Color> colors = new List<Color>();
                            colors.Add(StartColor);
                            colors.AddRange(GradientColor_.Select(x => x.Color));
                            colors.Add(EndColor);
                            List<float> points = new List<float>();
                            points.Add(0);
                            points.AddRange(GradientColor_.Select(x => x.ColorPositon));
                            points.Add(1);

                            ColorBlend = new ColorBlend()
                            {
                                Colors = colors.ToArray(),
                                Positions = points.ToArray()
                            };
                            //var pb = new PathGradientBrush(Path);

                            //pb.InterpolationColors = ColorBlend;
                            //pb.CenterPoint = new PointF(GradientCenterPoint.X * w + DrawPoint.X * w, GradientCenterPoint.Y * h + DrawPoint.Y * h);
                            //pb.Transform = matrix;
                            //Brush = pb;
                            Brush = new PathGradientBrush(Path);
                            (Brush as PathGradientBrush).InterpolationColors = ColorBlend;
                            (Brush as PathGradientBrush).CenterPoint = new PointF(GradientCenterPoint.X * w + DrawPoint.X * w, GradientCenterPoint.Y * h + DrawPoint.Y * h);
                            (Brush as PathGradientBrush).Transform = matrix;
                            break;

                        default:
                            break;
                    }
                    break;
            }
        }

        #endregion Methods
    }
}